#pragma once
#include "Thread.hpp"
#include "Mutex.hpp"
#include <vector>
#include <queue>
#include <mutex>
#include <pthread.h>
#include "log.hpp"
const int gnum = 3;

template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadPool<T> *threadPool;
    std::string name;

public:
    ThreadData(ThreadPool<T> *tp, const std::string &n)
        : threadPool(tp), name(n)
    {
    }
};

template <class T>
class ThreadPool
{
private:
    static void *handlerTask(void *args)
    {
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args);
        while (true)
        {
            T t;
            {
                LockGuard LockGuard(td->threadPool->getMutex());
                // std::cout << td->threadPool->isQueueEmpty() << std::endl;
                while (td->threadPool->isQueueEmpty())
                {
                    td->threadPool->threadWait();
                }
                t = td->threadPool->pop();
            }
            t();
        }
        delete td;
        return nullptr;
    }
    ThreadPool(int num = gnum)
        : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        for (int i = 0; i < _num; i++)
        {
            _thread.push_back(new Thread());
        }
    }
    

public:
    void push(const T &t)
    {
        LockGuard lockguard(&_mutex);
        _queue.push(t);
        pthread_cond_signal(&_cond);
    }
    // 判断任务队列是否为空
    bool isQueueEmpty()
    {
        return _queue.empty();
    }
    void lockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }

    void unlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }

    void threadWait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    T pop()
    {
        T t = _queue.front();
        _queue.pop();
        return t;
    }

    void run()
    {
        for (const auto &t : _thread)
        {
            ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
            t->start(handlerTask, td);
            // std::cout << t->threadname() << " start ..." << std::endl;
            logMessage(NORMAL,"%s start ...",t->threadname().c_str());
        }
    }

    pthread_mutex_t *getMutex()
    {
        return &_mutex;
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        // 验证一下这里的类型
        for (const auto &t : _thread)
        {
            delete t;
        }
    }
    static ThreadPool<T> *getInstance()
    {
        if (nullptr == tp)
        {
            _singlock.lock();
            if (nullptr == tp)
            {
                tp = new ThreadPool<T>();
            }
            _singlock.unlock();
        }
        return tp;
    }

private:
    int _num;                      // 你创建线程的数量
    std::queue<T> _queue;          // 这里我查了，stl容器基于链表实现的 // 充当任务队列
    std::vector<Thread *> _thread; // 线程池的线程，用vector管理
    pthread_mutex_t _mutex;        // 定义一个锁对象
    pthread_cond_t _cond;          // 定义条件变量
    static std::mutex _singlock;
    static ThreadPool<T> *tp;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::tp = nullptr;
template <class T>
std::mutex ThreadPool<T>::_singlock; // 这是std里面的mutex ,跟linux里面的不一样